International aid may take the form of multilateral aid – provided through international bodies such as the UN, or NGOs such as Oxfam – or bilateral aid, which operates on a government-to-government basis. There is considerable debate about whether international aid works, in the sense of reducing poverty and stimulating development.
However, the effectiveness of aid is often diluted by corruption. Aid is invariably channeled through the governments of recipient countries, in which power is often concentrated in the hands of a few politicians and bureaucrats, and the mechanisms of accountability are, at best, poorly developed. This tends to benefit corrupt leaders and elites rather than the people, projects and programs for which it was intended.
Watts, Carl. (2014). Re: Does foreign aid help the developing countries towards development?. Retrieved from: https://www.researchgate.net/post/Does_foreign_aid_help_the_developing_countries_towards_development/5322005ed039b1e7648b459c/citation/download.
The hypothesis that foreign aid can promote growth in developing countries was explored, using panel data series for foreign aid, while accounting for regional differences in Asian, African, Latin American, and the Caribbean countries as well as the differences in income levels, the results of this study also indicate that foreign aid has mixed effects on economic growth in developing countries.
Ekanayake, E. & Chatrna, Dasha. (2010). The effect of foreign aid on economic growth in developing countries. Journal of International Business and Cultural Studies. 3.
This study examines the relationships between foreign aid, institutional structure, and economic performance for 80 countries in Europe, America, Africa, and Asia. It is found that official development assistance and the quality of institutional structure in the sample countries affect economic growth positively.
Hayaloğlu, Pınar. (2023). Foreign Aid, Institutions, and Economic Performance in Developing Countries. Eskişehir Osmangazi Üniversitesi İktisadi ve İdari Bilimler Dergisi. 18. 748-765. 10.17153/oguiibf.1277348.
Algunas librerias y paquetes usados para obtener y descargar los datos
library(tidyverse) # manejo de dataframes
library(reshape2) # para tranfromar data de long a wide
library(WDI) # libreria para acceder a metadata de banco mundial
library(readxl) # leer archivos de excel
library(readr) # leer archivos csv
library(visdat) # visualizacion de datos como graficos
library(plotly) # graficos
library(purrr) # funcion map
library(plm) # modelos lineales para datos panel
library(car) # test y utilidades para modelos
library(htmltools) # para imprimir graficos en html
Datos para paises bajos ingresos sean utilizados, segun clasificación del banco mundial, hay 26 paises de bajos ingresos y 51 de ingresos medios bajos
country_class <- read_excel("CLASS.xlsx")
country_class %>%
filter(!is.na(Region), !is.na(`Income group`)) %>%
group_by(`Income group`) %>%
summarise(countries = n()) %>%
arrange(factor(`Income group`, levels = c('High income', 'Upper middle income', 'Lower middle income', 'Low income')))
Listado de paises a analisar:
my_countries <- country_class %>%
filter(!is.na(Region), `Income group` %in% c('Low income', 'Lower middle income')) %>%
select(Code)
my_countries %>% merge(country_class) %>% select(Code, Economy)
Hacer la respectiva asociacion de nombres iso3c e iso2c
my_countries$iso2c <- WDI_data$country %>%
filter(iso3c %in% my_countries$Code) %>%
.$iso2c
my_countries
Datos del banco mundial (para ODA y los indices de gobernanza) y el Human Development Reports API son descargados desde scripts de Python. Son almacenados en archivos CSV y luego son cargados aqui:
datos_HDI <- read_csv("datos_python_HDI.csv", col_names = c('Code', 'iso2c', 'indicator', 'year', 'value'),
col_types = list(col_character(), col_character(), col_character(), col_double(), col_double()))
hdi_indicators <- datos_HDI %>% distinct(indicator) %>% .$indicator
oda_indicators <- c(
'DT_ODA_ALLD_CD',
'DT_ODA_ALLD_KD',
'DT_ODA_OATL_CD',
'DT_ODA_OATL_KD',
'DT_ODA_ODAT_CD',
'DT_ODA_ODAT_GI_ZS',
'DT_ODA_ODAT_GN_ZS',
'DT_ODA_ODAT_KD',
'DT_ODA_ODAT_MP_ZS',
'DT_ODA_ODAT_PC_ZS',
'DT_ODA_ODAT_XP_ZS'
)
gob_indicators <- c(
'CC_EST',
'CC_NO_SRC',
'CC_PER_RNK',
'CC_PER_RNK_LOWER',
'CC_PER_RNK_UPPER',
'CC_STD_ERR',
'GE_EST',
'GE_NO_SRC',
'GE_PER_RNK',
'GE_PER_RNK_LOWER',
'GE_PER_RNK_UPPER',
'GE_STD_ERR',
'PV_EST',
'PV_NO_SRC',
'PV_PER_RNK',
'PV_PER_RNK_LOWER',
'PV_PER_RNK_UPPER',
'PV_STD_ERR',
'RQ_EST',
'RQ_NO_SRC',
'RQ_PER_RNK',
'RQ_PER_RNK_LOWER',
'RQ_PER_RNK_UPPER',
'RQ_STD_ERR',
'RL_EST',
'RL_NO_SRC',
'RL_PER_RNK',
'RL_PER_RNK_LOWER',
'RL_PER_RNK_UPPER',
'RL_STD_ERR',
'VA_EST',
'VA_NO_SRC',
'VA_PER_RNK',
'VA_PER_RNK_LOWER',
'VA_PER_RNK_UPPER',
'VA_STD_ERR'
)
gdp_indicators <- c(
'NY_ADJ_NNTY_PC_CD',
'NY_ADJ_NNTY_PC_KD',
'NY_ADJ_NNTY_PC_KD_ZG',
'NY_GDP_PCAP_CN',
'NY_GDP_PCAP_KN',
'NY_GDP_PCAP_CD',
'NY_GDP_PCAP_KD',
'NY_GDP_MKTP_KD_ZG',
'NY_GDP_DEFL_ZS_AD',
'NY_GDP_DEFL_ZS',
'NY_GDP_MKTP_CD',
'NY_GDP_MKTP_CN',
'NY_GDP_MKTP_KN',
'NY_GDP_MKTP_KD',
'NY_GDP_PCAP_KD_ZG',
'NY_GDP_PCAP_PP_KD',
'NY_GDP_PCAP_PP_CD',
'SL_GDP_PCAP_EM_KD',
'SP_POP_GROW'
)
datos_WB <- data.frame(indicator = character(), iso2c = character(), year = double(), value = double())
suppressWarnings(
for (indicator in c(oda_indicators, gob_indicators, gdp_indicators)) {
datos_WB <- rbind(datos_WB, read_csv(paste("datos_python", indicator, ".csv", sep =''),
col_names = c('indicator', 'iso2c', 'year', 'value'),
col_types = list(col_character(), col_character(), col_double(), col_double())))
}
)
Poverty <- read_excel("GlobalExtremePovertyDollaraDay_Compact.xlsx", sheet = "Data Long Format")
names(Poverty) <- c("ccode", "country", "year", "value")
Poverty[Poverty=="Cape Verde"] <- "Cabo Verde"
Poverty[Poverty=="Congo"] <- "Congo, Rep."
Poverty[Poverty=="Egypt"] <- "Egypt, Arab Rep."
Poverty[Poverty=="Iran"] <- "Iran, Islamic Rep."
Poverty[Poverty=="Kyrgyzstan"] <- "Kyrgyz Republic"
Poverty[Poverty=="Laos"] <- "Lao PDR"
Poverty[Poverty=="Macedonia"] <- "North Macedonia"
Poverty[Poverty=="Russia"] <- "Russian Federation"
Poverty[Poverty=="Slovakia"] <- "Slovak Republic"
Poverty[Poverty=="South Korea"] <- "Korea, Rep."
Poverty[Poverty=="Swaziland"] <- "Eswatini"
Poverty[Poverty=="Syria"] <- "Syrian Arab Republic"
Poverty[Poverty=="The Gambia"] <- "Gambia, The"
Poverty[Poverty=="Turkey"] <- "Turkiye"
Poverty[Poverty=="Venezuela"] <- "Venezuela, RB"
Poverty[Poverty=="Yemen"] <- "Yemen, Rep."
Poverty <- Poverty %>%
filter(year > 1994) %>%
merge(WDI_data$country, all.x = TRUE) %>%
mutate(indicator = 'POV') %>%
merge(my_countries) %>%
select(indicator, iso2c, year, value)
PC_LIB <- read_csv("political-civil-liberties-index.csv")
Rows: 33643 Columns: 4── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): Entity, Code
dbl (2): year, value
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
PC_LIB <- PC_LIB %>%
filter(year > 1994, !is.na(Code)) %>%
merge(my_countries) %>%
mutate(indicator = 'POL.CIV.LIB') %>%
select(indicator, iso2c, year, value)
datos_paper <- rbind(datos_WB, datos_HDI %>% select(indicator, iso2c, year, value), Poverty, PC_LIB) %>%
pivot_wider(names_from = indicator, values_from = value)
datos_paper <- datos_paper %>% mutate(GOV = (CC.EST + GE.EST + PV.EST + RQ.EST + RL.EST + VA.EST) / 6)
datos_paper <- datos_paper %>% arrange(iso2c, year) %>%
mutate(hdi_diff = case_when(iso2c == dplyr::lag(iso2c) ~ hdi - dplyr::lag(hdi), TRUE ~ NA_real_),
NY.GDP.PCAP.CD_diff = case_when(iso2c == dplyr::lag(iso2c) ~ NY.GDP.PCAP.CD - dplyr::lag(NY.GDP.PCAP.CD), TRUE ~ NA_real_),
DT.ODA.ALLD.CD_diff = case_when(iso2c == dplyr::lag(iso2c) ~ DT.ODA.ALLD.CD - dplyr::lag(DT.ODA.ALLD.CD), TRUE ~ NA_real_),
DT.ODA.ODAT.PC.ZS_diff = case_when(iso2c == dplyr::lag(iso2c) ~ DT.ODA.ODAT.PC.ZS - dplyr::lag(DT.ODA.ODAT.PC.ZS), TRUE ~ NA_real_),
GOV_diff = case_when(iso2c == dplyr::lag(iso2c) ~ GOV - dplyr::lag(GOV), TRUE ~ NA_real_),
POV_diff = case_when(iso2c == dplyr::lag(iso2c) ~ POV - dplyr::lag(POV), TRUE ~ NA_real_))
datos_paper <- datos_paper %>% mutate(GOV_GOOD = case_when(GOV >= 0 ~ 1, TRUE ~ 0))
plot_ly(data = datos_paper %>% filter(!is.na(GOV)), y = ~ GOV, type = 'scatter', mode = 'markers') %>%
layout(title = 'Indice promedio de gobernanza', xaxis = list(title = 'Registros'))
datos_paper <- datos_paper %>% mutate(POL.CIV.LIB_GOOD = case_when(POL.CIV.LIB >= 0.5 ~ 1, TRUE ~ 0))
plot_ly(data = datos_paper %>% filter(!is.na(POL.CIV.LIB)), y = ~ POL.CIV.LIB, type = 'scatter', mode = 'markers') %>%
layout(title = 'Indice libertades politicas y civiles', xaxis = list(title = 'Registros'))
datos_paper <- datos_paper %>% mutate(DT.ODA.ALLD.CD_LOG = log(DT.ODA.ALLD.CD))
Warning: NaNs produced
datos_paper <- datos_paper %>% mutate(DT.ODA.ODAT.PC.ZS_2 = DT.ODA.ODAT.PC.ZS ^ 2,
DT.ODA.ALLD.CD_2 = DT.ODA.ALLD.CD ^ 2,
DT.ODA.ALLD.CD_LOG_2 = DT.ODA.ALLD.CD_LOG ^ 2,)
vis_dat(datos_paper %>% select(all_of(gsub("_", ".", oda_indicators))))
# DT.ODA.OATL.CD and DT.ODA.OATL.KD faltan
# DT.ODA.ODAT.GI.ZS, DT.ODA.ODAT.GN.ZS, DT.ODA.ODAT.MP.ZS and DT.ODA.ODAT.XP.ZS tienen faltas
# Un par de ocurrencias pais-año que faltan datos
vis_dat(datos_paper %>% select(NY.GDP.PCAP.CN, NY.GDP.PCAP.CD))
# NY.GDP.PCAP.CN, NY.GDP.PCAP.CD, NY.GDP.MKTP.CD, NY.GDP.MKTP.CN son buenos candidatos para usar como variables,
# 'SY'falta PIB per Capita en 2022, 2023 sin datos algunos paises
vis_dat(datos_paper %>% arrange(year) %>% select(all_of(gsub("_", ".", gob_indicators))))
# Datos del 2000 para atras tienen espacios faltantes
vis_dat(datos_paper %>% select(all_of(hdi_indicators)))
# abr, co2_prod, le, le_f, le_m, mmr son las pocas categorias sin datos faltantes
# hdi faltante en multiples ocaciones
vis_dat(datos_paper %>% arrange(iso2c) %>% select(SP.POP.GROW))
# ZW no tiene datos de crecimiento poblacional
vis_dat(datos_paper %>% arrange(year, iso2c) %>% select(POV))
# 'AF', 'CD', 'CI', 'DJ', 'KH', 'LR', 'MR', 'PG', 'ST', 'TJ', 'UZ', 'VN', 'WS' no tienen datos de esta variable
# Porcentaje de personas por debajo de la linea de extrema pobreza (Dollar a day)
vis_dat(datos_paper %>% arrange(iso2c) %>% select(POL.CIV.LIB))
# KI MR SD WS son paises sin datos para estos años
# variables de etiqueta
ve <- c('iso2c', 'year')
# variables depndientes
vd <- c('hdi')
# 'hdi', 'hdi_diff', 'NY.GDP.PCAP.CD', 'NY.GDP.PCAP.CD_diff', 'POV', 'POV_diff',
# variables independientes
vi <- c('DT.ODA.ODAT.PC.ZS')
# 'DT.ODA.ODAT.PC.ZS', 'DT.ODA.ALLD.CD', 'DT.ODA.ALLD.CD_diff', 'DT.ODA.ODAT.PC.ZS_diff',
# 'DT.ODA.ALLD.CD:LOG'
# variables de control
vc <- c('NY.GDP.PCAP.CD',
'GOV',
'SP.POP.GROW',
'DT.ODA.ODAT.PC.ZS_2')
# 'SP.POP.GROW', 'CC.EST', 'GE.EST', 'PV.EST', 'RQ.EST', 'RL.EST', 'VA.EST', 'GOV', 'GOV_diff'
# 'NY.GDP.PCAP.CD', 'POL.CIV.LIB', 'DT.ODA.ODAT.PC.ZS_2', 'DT.ODA.ALLD.CD_2', 'DT.ODA.ALLD.CD_LOG_2'
# variables interactivas
vint <- c('GOV_GOOD') # 'GOV_GOOD', 'POL.CIV.LIB_GOOD'
# paises sin datos
delete_c <- c('SS', 'ZW', 'BT', 'ER', 'GW', 'KP', 'LB', 'NG', 'PS', 'SO', 'VU', 'FM', 'KI', 'TL', 'CV', 'SB', 'SY')
#, 'KI', 'MR', 'SD', 'WS' Si se usa POL.CIV.LIB
#, 'AF', 'CD', 'CI', 'DJ', 'KH', 'LR', 'MR', 'PG', 'ST', 'TJ', 'UZ', 'VN', 'WS' Si se usa POV
#, 'LK', 'PH' Si se usa DT.ODA.ALLD.CD_LOG
# años sin datos
first_y <- 2002
last_y <- 2022 # 2018 si se usa POV
f <- paste(vd, '~', case_when(length(vint) > 0 ~ paste(vi, vint, sep = '*'), TRUE ~ vi), '+', paste(vc, collapse = ' + '))
datos_model <- datos_paper %>%
filter(!iso2c %in% delete_c, !year < first_y, !year > last_y) %>%
select(all_of(c(ve, vd, vi, vc, vint)))
datos_model
vis_dat(datos_model)
Se revisara las relaciones entre las variables graficamente
my_plot = list()
for (vd_ in vd) {
for (vi_ in c(vi, vc)){
fit <- lm(paste(vd_, '~', vi_) ,data = datos_model)
my_plot[[paste(vd_,vi_)]] <- plot_ly(x = datos_model[[vi_]],
y = datos_model[[vd_]],
type = 'scatter',
mode = 'markers',
name = vi_) %>%
add_lines(x = datos_model[[vi_]], fitted(fit), name = paste("trace", vi_))
}
}
subplot(my_plot, nrows = 2, margin = 0.05) %>% layout(title = vd)
NA
model_ols <- lm(f, data=datos_model)
model_fe <- plm(f, data=datos_model, index = ve, model = "within")
model_re <- plm(f, data=datos_model, index = ve, model = "random")
print(f)
[1] "hdi ~ DT.ODA.ODAT.PC.ZS*GOV_GOOD + NY.GDP.PCAP.CD + GOV + SP.POP.GROW + DT.ODA.ODAT.PC.ZS_2"
summary(model_ols)
Call:
lm(formula = f, data = datos_model)
Residuals:
Min 1Q Median 3Q Max
-0.242596 -0.036234 0.002667 0.036458 0.273790
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.335e-01 8.157e-03 65.402 < 2e-16 ***
DT.ODA.ODAT.PC.ZS -2.476e-04 6.635e-05 -3.732 0.000199 ***
GOV_GOOD 7.539e-02 2.074e-02 3.636 0.000288 ***
NY.GDP.PCAP.CD 6.086e-05 2.108e-06 28.879 < 2e-16 ***
GOV 2.404e-02 4.884e-03 4.923 9.67e-07 ***
SP.POP.GROW -2.700e-02 2.082e-03 -12.970 < 2e-16 ***
DT.ODA.ODAT.PC.ZS_2 7.016e-07 2.139e-07 3.280 0.001068 **
DT.ODA.ODAT.PC.ZS:GOV_GOOD -3.665e-04 1.110e-04 -3.301 0.000991 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.06834 on 1252 degrees of freedom
Multiple R-squared: 0.5845, Adjusted R-squared: 0.5822
F-statistic: 251.6 on 7 and 1252 DF, p-value: < 2.2e-16
residualPlots(model_ols)
Test stat Pr(>|Test stat|)
DT.ODA.ODAT.PC.ZS 0.2716 0.786003
GOV_GOOD 0.0034 0.997324
NY.GDP.PCAP.CD -9.8249 < 2.2e-16 ***
GOV -1.4463 0.148358
SP.POP.GROW 5.0591 4.841e-07 ***
DT.ODA.ODAT.PC.ZS_2 -3.0343 0.002461 **
Tukey test -9.1197 < 2.2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
plot(model_ols)
vif(model_ols)
DT.ODA.ODAT.PC.ZS GOV_GOOD NY.GDP.PCAP.CD GOV
6.482080 3.566314 1.304431 1.365915
SP.POP.GROW DT.ODA.ODAT.PC.ZS_2 DT.ODA.ODAT.PC.ZS:GOV_GOOD
1.147912 16.752242 12.163939
print(f)
[1] "hdi ~ DT.ODA.ODAT.PC.ZS*GOV_GOOD + NY.GDP.PCAP.CD + GOV + SP.POP.GROW + DT.ODA.ODAT.PC.ZS_2"
summary(model_fe)
Oneway (individual) effect Within Model
Call:
plm(formula = f, data = datos_model, model = "within", index = ve)
Balanced Panel: n = 60, T = 21, N = 1260
Residuals:
Min. 1st Qu. Median 3rd Qu. Max.
-0.0953410 -0.0179084 0.0010104 0.0185345 0.1224959
Coefficients:
Estimate Std. Error t-value Pr(>|t|)
DT.ODA.ODAT.PC.ZS 2.5096e-04 4.5507e-05 5.5147 4.279e-08 ***
GOV_GOOD 2.6196e-03 1.0763e-02 0.2434 0.807739
NY.GDP.PCAP.CD 4.2953e-05 1.5323e-06 28.0315 < 2.2e-16 ***
GOV 2.0516e-02 5.1705e-03 3.9680 7.680e-05 ***
SP.POP.GROW -4.2837e-03 1.5386e-03 -2.7841 0.005452 **
DT.ODA.ODAT.PC.ZS_2 -5.0963e-07 1.1826e-07 -4.3093 1.773e-05 ***
DT.ODA.ODAT.PC.ZS:GOV_GOOD 7.7792e-05 7.2641e-05 1.0709 0.284425
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Total Sum of Squares: 1.7772
Residual Sum of Squares: 0.96099
R-Squared: 0.45927
Adj. R-Squared: 0.42935
F-statistic: 144.751 on 7 and 1193 DF, p-value: < 2.22e-16
#summary(lm(paste(f, '+ iso2c'), data=datos_model))
print(f)
[1] "hdi ~ DT.ODA.ODAT.PC.ZS*GOV_GOOD + NY.GDP.PCAP.CD + GOV + SP.POP.GROW + DT.ODA.ODAT.PC.ZS_2"
summary(model_re)
Oneway (individual) effect Random Effect Model
(Swamy-Arora's transformation)
Call:
plm(formula = f, data = datos_model, model = "random", index = ve)
Balanced Panel: n = 60, T = 21, N = 1260
Effects:
var std.dev share
idiosyncratic 0.0008055 0.0283817 0.175
individual 0.0038072 0.0617027 0.825
theta: 0.9001
Residuals:
Min. 1st Qu. Median 3rd Qu. Max.
-0.0992346 -0.0169620 0.0027149 0.0180997 0.1189000
Coefficients:
Estimate Std. Error z-value Pr(>|z|)
(Intercept) 4.8502e-01 1.0217e-02 47.4713 < 2.2e-16 ***
DT.ODA.ODAT.PC.ZS 2.3327e-04 4.5171e-05 5.1642 2.414e-07 ***
GOV_GOOD 3.9451e-03 1.0822e-02 0.3645 0.7154602
NY.GDP.PCAP.CD 4.3774e-05 1.5279e-06 28.6489 < 2.2e-16 ***
GOV 2.2027e-02 5.0463e-03 4.3649 1.272e-05 ***
SP.POP.GROW -5.2621e-03 1.5325e-03 -3.4338 0.0005953 ***
DT.ODA.ODAT.PC.ZS_2 -4.7767e-07 1.1791e-07 -4.0510 5.099e-05 ***
DT.ODA.ODAT.PC.ZS:GOV_GOOD 7.0208e-05 7.2070e-05 0.9742 0.3299756
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Total Sum of Squares: 1.8998
Residual Sum of Squares: 1.0258
R-Squared: 0.46004
Adj. R-Squared: 0.45702
Chisq: 1066.7 on 7 DF, p-value: < 2.22e-16
print(f)
[1] "hdi ~ DT.ODA.ODAT.PC.ZS*GOV_GOOD + NY.GDP.PCAP.CD + GOV + SP.POP.GROW + DT.ODA.ODAT.PC.ZS_2"
phtest(model_fe, model_re)
Hausman Test
data: f
chisq = 43.497, df = 7, p-value = 2.673e-07
alternative hypothesis: one model is inconsistent
save(f, delete_c, first_y, last_y, my_plot, model_ols, model_fe, model_re, file = "HID_ODAPCGOVGOOD_GDPPC_GOV_GROW.RData")